//---------------------------------------------------------------------------

#ifndef h_lgexprH
#define h_lgexprH
//---------------------------------------------------------------------------
class HLex
{
public :
   HLex(const vector<HString> &Text);
   ~HLex(void);

// 单引号括起来的是常量字符串，其中 \' 表示单引号本身
// 如果右边单引号缺失就认为字符串到行尾结束
// \n \t 转换成空格
// 数字常量 [+|-]99*[.99*] 作为一个单词
// >= 和 <= 作为一个单词
// 除了字母、数字、减号（-）、下划线（_）之外的字符均作为分隔符
// 每次获得的单词的首尾空格去除
// 如果获得的是常量字符串，则第一个字符是单引号（'），后面是常量
// 串的内容，最后不加单引号
// 到数据流尾返回false

   bool GetToken(HString &Token);
   void UnGetToken(const HString &Token);
   int GetLine(void);
   int GetCol(void);

private :

   char PeekChar(void);
   void Advance(void);
   bool IsCharInVar(char c);

   const vector<HString> &FText;
   bool FUnGetTokenFlag;
   HString FUnGetToken;
   int FLine;
   int FCol;
};

class HLgExpr
{
public :
   typedef bool (*HIsValidVarName)(
      const HString &VarName);
   typedef bool (*HVarTypeIsNumeric)(
      const HString &VarName);
   typedef HString (*HGetVar)(
      const HString &VarName);

   HLgExpr(void);
   ~HLgExpr(void);

   static void Init(HIsValidVarName AIsValidVarName,
      HVarTypeIsNumeric AVarTypeIsNumeric, HGetVar AGetVar);
   static HString GetErrorString(void);
   static bool Compare(const HString &Func,
      const HString &Value1, const HString &Value2, bool NumericCompare);
   static HString GetRegularNumber(const HString &Value);

   bool Parse(const vector<HString> &Text);
   bool Execute(void) const;

private :
   bool GetNode(HLex &Lex, HLgExpr * &Node);

   enum HLogicOperator { loValue, loFunc, loAnd, loOr };
   HLogicOperator Op;
// if Op == loValue
   bool IsVar;
   HString Value; // if IsVar VarName else Const Value
// if Op == loFunc
   HString Func; // =, >, <, >=, <=
   bool NumericCompare;
// if Op == loFunc || Op == loAnd || Op == loOr
   bool Not;
   HLgExpr *Left;
   HLgExpr *Right;

   static HIsValidVarName IsValidVarName;
   static HVarTypeIsNumeric VarTypeIsNumeric;
   static HGetVar GetVar;
   static HString FErrorString;
};

#endif
